/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sync.services;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.entity.ContentProducer;
import org.apache.http.entity.EntityTemplate;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils;
import sync.model.Assignment;
import sync.model.AssignmentItem;

/**
 *
 * @author yarden
 */
public class ChartReaderService {
    
    public final int    RESPONSE_OK         = 200;
    public final String SERVICE             = "annotation-ws/";
    
    public final String GET_ASSIGNMENT      = "rest/assignment/";
    public final String GET_ASSIGNMENT_ITEM = "rest/unitOfAnalysis/"; 
    public final String GET_SCHEMA          = "rest/schema/";
    
    HttpHost host;
    BasicHttpContext context;
    
    public ChartReaderService(String url, int port) {
        host = new HttpHost(url,port, "http");
    }
    
    
    
    public List<Assignment> getAssignments(String user) throws SyncException {
        return new AssignmentsParser().parseAssignments(getFromServer(GET_ASSIGNMENT+user));
    }
    
    
    public String getSchema(String schemaId) throws SyncException {
        return new SchemaParser().parse(getFromServer(GET_SCHEMA+schemaId));
    }
    
    public String getAssignmentItem(AssignmentItem item) throws SyncException {
        return new AssignmentItemParser().parse(getFromServer(GET_ASSIGNMENT_ITEM+item.getId()));
    }
    
    public void updateAssignments(String user, List<AssignmentItem> items)  {
        try {
            new AssignmentsParser().getContentProcuder(items).writeTo(System.out);
        } catch (IOException ex) {
            Logger.getLogger(ChartReaderService.class.getName()).log(Level.SEVERE, null, ex);
        }
        sendToServer(GET_ASSIGNMENT+user, new AssignmentsParser().getContentProcuder(items));
    }
    
    public void connect(String user, String password) {
        DefaultHttpClient client = new DefaultHttpClient();
        
        client.getCredentialsProvider().setCredentials(
                new AuthScope(host.getHostName(), host.getPort()),
                new UsernamePasswordCredentials(user, password));
        
         AuthCache cache = new BasicAuthCache();
         BasicScheme auth = new BasicScheme();
         cache.put(host, auth);
         
         context = new BasicHttpContext();
         context.setAttribute(ClientContext.AUTH_CACHE, cache);
         
         HttpGet get = new HttpGet("/");
         for (int i=0; i<3; i++) {
            try {
                HttpResponse response = client.execute(host, get, context);
                HttpEntity entity = response.getEntity();
                EntityUtils.consume(entity);
            } catch (ClientProtocolException ex) {
                Logger.getLogger(ChartReaderService.class.getName()).log(Level.SEVERE, null, ex);
            }  catch (IOException ex) {
                Logger.getLogger(ChartReaderService.class.getName()).log(Level.SEVERE, null, ex);
            }
         }
    }
    
    private InputStream getFromServer(String request) throws SyncException {
        
        try {
            HttpClient client = new DefaultHttpClient();
            URI uri = URIUtils.createURI("http", host.getHostName(), host.getPort(), SERVICE+request, null, null);
                    
            HttpGet get = new HttpGet(uri);
            HttpResponse response = client.execute(get);
            if (response.getStatusLine().getStatusCode() != RESPONSE_OK)
                throw new SyncException("Server communication error: "+response.getStatusLine().getReasonPhrase());
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                return entity.getContent();
            }
            
        } catch (URISyntaxException ex) {
            Logger.getLogger(ChartReaderService.class.getName()).log(Level.SEVERE, null, ex);
            throw(new SyncException(ex.getLocalizedMessage(), ex));
        } catch (ClientProtocolException ex) {
            Logger.getLogger(ChartReaderService.class.getName()).log(Level.SEVERE, null, ex);
            throw(new SyncException(ex.getLocalizedMessage(), ex));
        } catch (IOException ex) {
            Logger.getLogger(ChartReaderService.class.getName()).log(Level.SEVERE, null, ex);
            throw(new SyncException(ex.getLocalizedMessage(), ex));
        } 
        
        return null;     
    }
    
    private void sendToServer(String command, ContentProducer producer) {
        
        try {
            HttpClient client = new DefaultHttpClient();
            URI uri = URIUtils.createURI("http", host.getHostName(), host.getPort(), SERVICE+command, null, null);
            HttpEntity entity = new EntityTemplate(producer);
            
            HttpPut put = new HttpPut(uri);
            put.setEntity(entity);
            client.execute(put);
        } catch (URISyntaxException ex) {
            Logger.getLogger(ChartReaderService.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClientProtocolException ex) {
            Logger.getLogger(ChartReaderService.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ChartReaderService.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    
}
